from random import random
import random
from django import forms
from django.conf import settings
from django.core.exceptions import ValidationError
from django_redis import get_redis_connection

from utils import encrypt
from utils.tencent.sms import send_sms_single
from web import models  # 使用web 的models生成表
from django.core.validators import RegexValidator

# forms可以生成表单，还可以校验数据
# 自动让表生成表单HTML
from web.forms.bootstrap import BootStrapForm


class RegisterModelForm(forms.ModelForm):
    # #mobile_phone=forms.EmailField(label="邮箱2")  将表中的字段名重命名
    # # 由于没有提供手机格式的校验，自己写一个正则表达式
    orgname = forms.CharField(label="单位名", min_length=2,
                              max_length=15,
                              error_messages={
                                  'min_length': "单位名长度不能小于2个字符",
                                  'max_length': "单位名长度不能大于15个字符"
                              }, )

    org_id = forms.CharField(label="单位简写", min_length=2,
                             max_length=10,
                             error_messages={
                                 'min_length': "密码长度不能小于2个字符",
                                 'max_length': "密码长度不能大于10个字符"
                             }, )
    mobile_phone = forms.CharField(label="手机号", validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式错误'), ])
    # 这个字段会走这个正则表达式
    password = forms.CharField(label="密码",
                               min_length=8,
                               max_length=64,
                               error_messages={
                                   'min_length': "密码长度不能小于8个字符",
                                   'max_length': "密码长度不能大于64个字符"
                               },
                               widget=forms.PasswordInput())  # 根据widget插件展示

    confirm_password = forms.CharField(label="重复密码",

                                       min_length=8,
                                       max_length=64,
                                       error_messages={
                                           'min_length': "重复密码长度不能小于8个字符",
                                           'max_length': "重复密码长度不能大于64个字符"
                                       },
                                       widget=forms.PasswordInput())
    # # 没有这个label就添加一个，有就覆盖

    code = forms.CharField(label="验证码", widget=forms.TextInput())  # 可以添加widget和validators插件

    # # 生成普通input标签

    class Meta:
        model = models.organization
        # fields = "__all__"
        # 自定义字段顺序__all__是默认顺序
        fields = ["orgname", "org_id", "username", "password", "confirm_password", "mobile_phone", "code"]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for name, field in self.fields.items():  # 变历字典，name是字段，field是对应的对象
            field.widget.attrs["class"] = 'form-control'
            field.widget.attrs["placeholder"] = "请输入合法的%s" % field.label


    def clean_username(self):
        username = self.cleaned_data['username']  # 获取request.POST的值
        if len(username)>10:
            raise ValidationError('用户名不能大于10')
            # self.add_error('username','用户名已存在')
        return username

    def clean_orgname(self):
        orgname = self.cleaned_data['orgname']
        flge = True
        for ch in orgname:
            if u'\u4e00' <= ch <= u'\u9fff':
                pass
            else:
                flge = False

        if flge:
            if len(orgname) <= 0 or len(orgname) > 15:
                raise ValidationError('公司名不为空或者不超过15个字符')
        else:
            raise ValidationError('公司名必须是全部的中文名')
        print("3")
        return orgname

    def clean_org_id(self):
        org_id = self.cleaned_data['org_id']
        print("4")
        exists = models.organization.objects.filter(org_id=org_id).exists()
        if exists:
            raise ValidationError('公司简名以存在')
        if org_id.isupper():
            if len(org_id) <= 0 or len(org_id) > 15:
                raise ValidationError('公司简写不能为空或者超过10个字符')
        else:
            raise ValidationError('公司名必须是全英文大写')
        return org_id

    def clean_password(self):
        pwd = self.cleaned_data['password']
        # 加密 & 返回
        return encrypt.md5(pwd)

    def clean_confirm_password(self):
        pwd = self.cleaned_data.get('password')
        confirm_pwd = encrypt.md5(self.cleaned_data['confirm_password'])
        if pwd != confirm_pwd:
            raise ValidationError('两次密码不一致')
        return confirm_pwd
    def clean_mobile_phone(self):
        print("7")
        mobile_phone = self.cleaned_data['mobile_phone']
        exists = models.organization.objects.filter(mobile_phone=mobile_phone).exists()
        exists1=models.guser.objects.filter(mobile_phone=mobile_phone).exists()
        if exists:
            raise ValidationError('手机号已注册')
        if exists1:
            raise ValidationError('手机号已经注册为普通人员，可以登陆')
        return mobile_phone
    def clean_code(self):
        print("8")
        code = self.cleaned_data['code']
        # mobile_phone = self.cleaned_data['mobile_phone']
        mobile_phone = self.cleaned_data.get('mobile_phone')
        if not mobile_phone:
            return code
        conn = get_redis_connection()
        redis_code = conn.get(mobile_phone)
        if not redis_code:
            raise ValidationError('验证码失效或未发送，请重新发送')

        redis_str_code = redis_code.decode('utf-8')

        if code.strip() != redis_str_code:
            raise ValidationError('验证码错误，请重新输入')

        return code


# # 自定义校验的数据
class SendSmsForm(forms.Form):
    mobile_phone = forms.CharField(label='手机号', validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式错误'), ])

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean_mobile_phone(self):
        """ 手机号校验的钩子 """
        print(self.cleaned_data['mobile_phone'])
        mobile_phone = self.cleaned_data['mobile_phone']

        # 判断短信模板是否有问题
        tpl = self.request.GET.get('tpl')
        print(tpl)

        template_id = settings.TENCENT_SMS_TEMPLATE.get(tpl)
        if not template_id:
            # self.add_error('mobile_phone','短信模板错误')
            raise ValidationError('短信模板错误')


        existsdw = models.organization.objects.filter(mobile_phone=mobile_phone).exists()
        existsgr = models.guser.objects.filter(mobile_phone=mobile_phone).exists()
        if tpl == 'login':
            if not existsdw and not existsgr:
                raise ValidationError('手机号不存在')
        else:
            # 校验数据库中是否已有手机号
            if existsgr or existsgr:
                raise ValidationError('手机号已存在')

        # 判断一下是否是多次发送
        conn = get_redis_connection()
        if conn.get(mobile_phone):  # 如果已经有了电话号码
            raise ValidationError("请勿频繁发送短信，每次间隔时间为60秒")
        else:
            # 发送短信
            code = random.randrange(1000, 9999)
            # sms = send_sms_single(mobile_phone, template_id, [code, ])
            # if sms['result'] != 0:
            #     raise ValidationError("短信发送失败，{}".format(sms['errmsg']))
            print("短信验证码是：", code)

            # 验证码 写入redis（django-redis）
            conn.set(mobile_phone, code, ex=60)

        return mobile_phone


class LoginSMSForm(BootStrapForm, forms.Form):
    # 校验登陆的手机号和验证码
    mobile_phone = forms.CharField(
        label='手机号',
        validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式错误'), ]
    )

    code = forms.CharField(
        label='验证码',
        widget=forms.TextInput())

    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data['mobile_phone']


        existsdw = models.organization.objects.filter(mobile_phone=mobile_phone).exists()

        existsgr = models.guser.objects.filter(mobile_phone=mobile_phone).exists()


        if existsgr or existsdw:
            return mobile_phone
        else:
            raise ValidationError('手机号不存在')


    def clean_code(self):
        code = self.cleaned_data['code']
        mobile_phone = self.cleaned_data.get('mobile_phone')

        # 手机号不存在，则验证码无需再校验
        if not mobile_phone:
            return code

        conn = get_redis_connection()
        redis_code = conn.get(mobile_phone)  # 根据手机号去获取验证码
        if not redis_code:
            raise ValidationError('验证码失效或未发送，请重新发送')

        redis_str_code = redis_code.decode('utf-8')

        if code.strip() != redis_str_code:
            raise ValidationError('验证码错误，请重新输入')

        return code


class LoginForm(BootStrapForm, forms.Form):
    "手机号密码登陆"
    username = forms.CharField(label='手机号')
    password = forms.CharField(label='密码', widget=forms.PasswordInput(render_value=True))
    code = forms.CharField(label='图片验证码')


    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean_password(self):
        pwd = self.cleaned_data['password']
        # 加密 & 返回
        return encrypt.md5(pwd)

    def clean_code(self):
        """ 钩子 图片验证码是否正确？ """
        # 读取用户输入的yanzhengm
        code = self.cleaned_data['code']

        # 去session获取自己的验证码
        session_code = self.request.session.get('image_code')
        if not session_code:
            raise ValidationError('验证码已过期，请重新获取')

        if code.strip().upper() != session_code.strip().upper():
            raise ValidationError('验证码输入错误')

        return code


class GregisterForm(forms.ModelForm):
    invite = forms.CharField(label='单位邀请码',
                             max_length=8,
                             error_messages={
                                 'max_length': "邀请码长度不合法"
                             },

                             )
    bumen = forms.CharField(label='部门',
                             max_length=20,
                             error_messages={

                                 'max_length': "部门字数不能超过20"
                             },

                             )

    password = forms.CharField(
        label='密码',
        min_length=8,
        max_length=64,
        error_messages={
            'min_length': "密码长度不能小于8个字符",
            'max_length': "密码长度不能大于64个字符"
        },
        widget=forms.PasswordInput()
    )
    confirm_password = forms.CharField(
        label='重复密码',
        min_length=8,
        max_length=64,
        error_messages={
            'min_length': "重复密码长度不能小于8个字符",
            'max_length': "重复密码长度不能大于64个字符"
        },
        widget=forms.PasswordInput())

    mobile_phone = forms.CharField(label='手机号', validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式错误'), ])

    code = forms.CharField(
        label='验证码',
        widget=forms.TextInput())


    class Meta:
        model = models.guser
        # fields = "__all__"
        # 自定义字段顺序__all__是默认顺序
        fields = ["invite","bumen", "job_id","username","gender",'age', "password", "confirm_password", "mobile_phone", "code"]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for name, field in self.fields.items():  # 变历字典，name是字段，field是对应的对象
            field.widget.attrs["class"] = 'form-control'
            field.widget.attrs["placeholder"] = "请输入合法的%s" % field.label
    def clean_invite(self):  # 判断邀请码是否合法
        invite = self.cleaned_data['invite']
        invite_object = models.invite.objects.filter(invite=invite).first()

        if invite_object:

            if invite_object.status==1:
                return invite
            else:
                raise ValidationError('邀请码未启用')
        else:
            raise ValidationError('邀请码错误')


    def clean_username(self):
        username = self.cleaned_data['username']

        if len(username)>10:
            raise ValidationError('用户名不能大于10')
            # self.add_error('username','用户名已存在')
        return username

    def clean_age(self):
        age = self.cleaned_data['age']

        if age<10 or age>120 :
            raise ValidationError('年龄不符合')
            # self.add_error('username','用户名已存在')
        return age

    def clean_job_id(self):
        job_id = self.cleaned_data['job_id']
        invite = self.cleaned_data.get('invite')
        invite_object=models.invite.objects.filter(invite=invite).first()
        exists= models.guser.objects.filter(org_id=invite_object.org_id).filter(job_id=job_id).exists()
        if  exists:
           raise ValidationError('工号/学号以被注册')
        if len(job_id)>=15 :
            raise ValidationError('工号/学号小于15个字符')
            # self.add_error('username','用户名已存在')
        return job_id

    def clean_bumen(self):
        bumen = self.cleaned_data['bumen']
        if len(bumen) > 20:
            raise ValidationError('部门不能大于10')
            # self.add_error('username','用户名已存在')
        return bumen

    def clean_password(self):
        pwd = self.cleaned_data['password']
        # 加密 & 返回
        return encrypt.md5(pwd)

    def clean_confirm_password(self):
        pwd = self.cleaned_data.get('password')

        confirm_pwd = encrypt.md5(self.cleaned_data['confirm_password'])

        if pwd != confirm_pwd:
            raise ValidationError('两次密码不一致')

        return confirm_pwd

    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data['mobile_phone']
        exists = models.guser.objects.filter(mobile_phone=mobile_phone).exists()
        exists1= models.organization.objects.filter(mobile_phone=mobile_phone).exists()
        if exists or exists1:
            raise ValidationError('手机号已注册')
        return mobile_phone

    def clean_code(self):
        code = self.cleaned_data['code']

        # mobile_phone = self.cleaned_data['mobile_phone']

        mobile_phone = self.cleaned_data.get('mobile_phone')
        if not mobile_phone:
            return code

        conn = get_redis_connection()
        redis_code = conn.get(mobile_phone)
        if not redis_code:
            raise ValidationError('验证码失效或未发送，请重新发送')

        redis_str_code = redis_code.decode('utf-8')

        if code.strip() != redis_str_code: # .strip()去掉空格
            raise ValidationError('验证码错误，请重新输入')

        return code

